#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace std;

typedef void (*functor)();

vector<functor> functors;

unordered_map<uint32_t, string> info;

void f1()
{
    cout << "这是一个处理日志的任务，执行的进程 ID [" << getpid() << "]"
         << "执行时间是[" << time(nullptr) << "]" << endl;
}

void f2()
{
    cout << "这是一个备份数据的任务，执行的进程 ID [" << getpid() << "]"
         << "执行时间是[" << time(nullptr) << "]" << endl;
}

void f3()
{
    cout << "这是一个处理网络连接的任务，执行的进程 ID [" << getpid() << "]"
         << "执行时间是[" << time(nullptr) << "]" << endl;
}

void loadFunctor()
{
    info.insert({functors.size(), "处理日志的任务"});
    functors.push_back(f1);
    
    info.insert({functors.size(), "备份数据的任务"});
    functors.push_back(f2);

    info.insert({functors.size(), "处理网络连接的任务"});
    functors.push_back(f3);
}

typedef std::pair<int32_t, int32_t> elem;
int processNum = 5;

void work(int blockFd)
{
    cout << "进程[" << getpid() << "]" << "开始工作" << endl;

    while(true)
    {
        uint32_t operatorCode = 0;
        ssize_t s = read(blockFd, &operatorCode, sizeof(uint32_t));
        if(s == 0)
        {
            break;
        }
        
        assert(s == sizeof(uint32_t));
        (void)s;

        if(operatorCode < functors.size())
        {
            functors[operatorCode]();
        }
    }

    cout << "进程[" << getpid() << "]" << "结束工作" << endl;
}

void balanceSendTask(const vector<elem>& processFds)
{
    srand((long long)time(nullptr));
    while(true)
    {
        sleep(1);

        uint32_t pick = rand() % processFds.size();

        uint32_t task = rand() % functors.size();

        write(processFds[pick].second, &task, sizeof(task));

        cout << "父进程指派任务->" << info[task] << " 给进程: " << processFds[pick].first << "编号: " << pick << endl;
    }
}

int main()
{
    // 加载任务列表
    loadFunctor();
    vector<elem> assignMap;

    for(int i = 0; i < processNum; ++i)
    {
        int pipefd[2] = { 0 };
        pipe(pipefd);

        pid_t id = fork();
        if(id == 0)
        {
            close(pipefd[1]);

            work(pipefd[0]);
            exit(0);
        }

        close(pipefd[0]);
        elem e(id, pipefd[1]);
        assignMap.push_back(e);
    }
    cout << "create all process success!" << std::endl;

    balanceSendTask(assignMap);

    for(int i = 0; i < processNum; ++i)
    {
        if(waitpid(assignMap[i].first, nullptr, 0) > 0)
        {
            cout << "wait forL pid=" << assignMap[i].first << "wait success!"
                 << "number: " << i << std::endl;
        }

        close(assignMap[i].second);
    }

    return 0;
}